package com.terra.ns.imp.system.api

import cn.hutool.core.collection.CollUtil
import com.terra.ns.imp.common.core.constant.GlobalBoolEnum
import com.terra.ns.imp.common.mybatis.base.MpConstants
import com.terra.ns.imp.common.util.string.nullDefault
import com.terra.ns.imp.system.api.entity.*
import com.terra.ns.imp.system.api.service.IDeptApi
import com.terra.ns.imp.system.api.service.IUserApi
import com.terra.ns.imp.system.mapper.*
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service

/**
@author qins
@date 2023/6/1
@desc 用户信息API实现
 */
@Service
class UserApiImpl: IUserApi {

    @Autowired
    private lateinit var userMapper: StUserMapper

    @Autowired
    private lateinit var roleMapper: StRoleMapper

    @Autowired
    private lateinit var userRoleRelMapper: StUserRoleRelMapper

    @Autowired
    private lateinit var userDeptRelMapper: StUserDeptRelMapper

    @Autowired
    private lateinit var deptMapper: StDepartmentMapper

    @Autowired
    private lateinit var deptApi: IDeptApi

    override fun getUserByPhone(phone: String): StUser? =
        userMapper.selectOneByPhone(phone)

    override fun getUserRoles(userCode: String): List<BaseRole> {
        val userRoleRelList = userRoleRelMapper.selectListByUserCode(userCode)
        if(userRoleRelList.isEmpty()) return CollUtil.newArrayList()
        val roleList = roleMapper.selectListByCodes(userRoleRelList.mapNotNull { it.roleCode })
        return roleList.map { BaseRole(it.name.nullDefault(), it.code.nullDefault()) }
    }

    override fun getUserPerms(userCode: String): List<BasePerm> {
        // todo
        return CollUtil.newArrayList()
    }

    override fun getUserDepts(userCode: String): List<BaseDept> {
        val userDeptList = userDeptRelMapper.selectListByUserCode(userCode)
        if(userDeptList.isEmpty()) return CollUtil.newArrayList()
        val deptList = deptMapper.selectListByCodes(userDeptList.mapNotNull { it.departmentCode })
        return deptList.map{BaseDept(it.name.nullDefault(), it.code.nullDefault())}
    }

    override fun getUserDeptLeader(userCode: String): List<BaseDeptUser> {
        val userDeptRelList = userDeptRelMapper.selectListByUserCode(userCode)
        if(userDeptRelList.isEmpty()) return CollUtil.newArrayList()
        return deptApi.getDeptLeaderByDepts( userDeptRelList.mapNotNull { it.departmentCode })
    }

    override fun getUserDeptInfo(userCodes: List<String>): List<UserDeptInfo> {
        val result = ArrayList<UserDeptInfo>()
        if(userCodes.contains(MpConstants.SYSTEM_OPERATOR)) {
            result.add(UserDeptInfo(MpConstants.SYSTEM_OPERATOR, "", MpConstants.SYSTEM_OPERATOR_NAME, null, null))
        }
        val userList = userMapper.selectListByCodes(userCodes)
        if(userList.isEmpty()) return emptyList()
        val userDeptList = userDeptRelMapper.selectListByUserCodes(userCodes)
        val depts = deptMapper.selectListByCodes(userDeptList.mapNotNull { it.departmentCode }).associate { it.code to it.name }
        val userDeptMap = userDeptList.groupBy { it.userCode }
        result.addAll(userList.map { uc ->
            val userCode = uc.code!!
            val deptRelList = userDeptMap[userCode]
            val deptCode = deptRelList?.let { dls -> (dls.firstOrNull {it.mainDept == GlobalBoolEnum.YES.code} ?: dls[0]).departmentCode }
            UserDeptInfo(userCode, uc.phone.nullDefault(), uc.name.nullDefault(), deptCode, depts[deptCode])
        })
        return result
    }

    override fun getUserDeptInfo(userCode: String): UserDeptInfo? {
        if(userCode == MpConstants.SYSTEM_OPERATOR) {
            return UserDeptInfo(userCode, "", MpConstants.SYSTEM_OPERATOR_NAME, null, null)
        }
        val user = userMapper.selectOneByCode(userCode) ?: return null
        val userDeptRel = userDeptRelMapper.selectListByUserCode(userCode)
        var deptCode: String? = null
        if(userDeptRel.isNotEmpty()) {
            deptCode = (userDeptRel.firstOrNull {it.mainDept == GlobalBoolEnum.YES.code} ?: userDeptRel[0]).departmentCode
        }
        val dept = deptCode?.let { deptMapper.selectOneByCode(it) }
        return UserDeptInfo(userCode, user.phone.nullDefault(), user.name.nullDefault(), deptCode, dept?.name)
    }
}